#include "usart_drv.h"

// 定义一个usart的缓冲区
//static uint8_t UsartDmaDataBuff[USART_DMA_DATA_BUFF_LEN] = { 0 };

// 定义一个全局函数指针 当空闲中断发生时 被调用
//static void (*pProcUartIdelIteruptFunc)(uint8_t* data, uint32_t len);


/**
 * @desc  : 保存usart信息的结构体
 * @date  : 2025-06-20
 * @author: AnRui
 * @note  :
 */
UsartInfoStruct UsartInfo = {
    USART0,
    RCU_USART0,
    RCU_GPIOA,
    GPIOA,
    GPIO_PIN_9,
    GPIO_PIN_10,
    USART0_IRQn,
    DMA0,
    RCU_DMA0,
    DMA_CH4
};


/**
 * @desc  : usart 端口引脚初始化
 * @date  : 2025-03-25
 * @author: AnRui
 * @note  :
 */
static void  UsartGPIOInit() {
    rcu_periph_clock_enable(UsartInfo.rcuGpio);
    // 发送配置为推挽复用模式
    gpio_init(UsartInfo.gpio, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, UsartInfo.txPin);
    // 接收配置为上拉输入模式
    gpio_init(UsartInfo.gpio, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, UsartInfo.rxPin);
}


/**
 * @desc  : DMA配置
 * @date  : 2025-06-20
 * @author: AnRui
 * @note  :
 */
//static void  UsartDmaInit() {
//    /* 使能DMA时钟；*/
//    rcu_periph_clock_enable(UsartInfo.rcuDma);
//    /* 复位DMA通道；*/
//    dma_deinit(UsartInfo.dmaNo, UsartInfo.dmaCh);
//    dma_parameter_struct dmaStruct;
//    /* 配置传输方向；*/
//    dmaStruct.direction = DMA_PERIPHERAL_TO_MEMORY;
//    /* 配置数据源地址；(uint32_t)(&USART_DATA(UsartInfo.uartNo)) (USART0 + 0x04)*/
//    dmaStruct.periph_addr = (uint32_t)(&USART_DATA(UsartInfo.uartNo));
//    /* 配置源地址是固定的还是增长的；*/
//    dmaStruct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
//    /* 配置源数据传输位宽；*/
//    dmaStruct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
//    /* 配置数据目的地址；*/
//    dmaStruct.memory_addr = (uint32_t)UsartDmaDataBuff;
//    /* 配置目的地址是固定的还是增长的；*/
//    dmaStruct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
//    /* 配置目的数据传输位宽；*/
//    dmaStruct.memory_width = DMA_MEMORY_WIDTH_8BIT;
//    /* 配置数据传输最大次数；*/
//    dmaStruct.number = USART_DMA_DATA_BUFF_LEN;
//    /* 配置DMA通道优先级；*/
//    dmaStruct.priority = DMA_PRIORITY_HIGH;
//    // 如果不配置循环模式  达到最大搬运次数就停止  配置循环会把超过的搬运到初始位置
//    dma_init(UsartInfo.dmaNo, UsartInfo.dmaCh, &dmaStruct);

//    /* 使能UART接收数据使用DMA；*/
//    //
//    usart_dma_receive_config(UsartInfo.uartNo, USART_RECEIVE_DMA_ENABLE);
//    /* 使能DMA通道；*/
//    dma_channel_enable(UsartInfo.dmaNo, UsartInfo.dmaCh);

//}

/**
 * @desc  : usart外设初始化
 * @date  : 2025-03-25
 * @author: AnRui
 * @note  : usart使能 配置数据位数 校验位 停止位 发送功能开启等
 */
static void  UsartPeriphInit() {
    /* 使能UART时钟；*/
    rcu_periph_clock_enable(UsartInfo.rcuUart);
    /* 复位UART；*/
    usart_deinit(UsartInfo.uartNo);
    /* 数据长度*/
    usart_word_length_set(UsartInfo.uartNo, USART_WL_8BIT);
    /* 从低位开始发送*/
    usart_data_first_config(UsartInfo.uartNo, USART_MSBF_LSB);
    /* 校验位*/
    usart_parity_config(UsartInfo.uartNo, USART_PM_NONE);
    /* 停止位*/
    usart_stop_bit_set(UsartInfo.uartNo, USART_STB_1BIT);
    /* 波特率*/
    usart_baudrate_set(UsartInfo.uartNo, BAUDRATE);
    /* 使能发送功能；*/
    usart_transmit_config(UsartInfo.uartNo, USART_TRANSMIT_ENABLE);
    /* 在USART_CTL0寄存器中设置TEN位，使能接收功能；*/
    usart_receive_config(UsartInfo.uartNo, USART_RECEIVE_ENABLE);
    /* 使能串口接收中断；*/
    // USART_INT_TBE:发送寄存器为空   USART_FLAG_TC:移位寄存器为空 USART_INT_RBNE:接受缓冲区(非空)收到数据  USART_INT_IDLE: 检测到总线空闲（持续高电平超过一帧时间）可以认为 数据接收完成
//    usart_interrupt_enable(UsartInfo.uartNo, USART_INT_IDLE);
		usart_interrupt_enable(UsartInfo.uartNo, USART_INT_RBNE);
    /* 使能串口中断；*/
    nvic_irq_enable(UsartInfo.irq, USART_INT_PRIORITY);
    /* 在USART_CTL0寄存器中置位UEN位，使能UART；*/
    usart_enable(UsartInfo.uartNo);
}

/**
 * @desc  : 发送1byte数据
 * @date  : 2025-03-25
 * @author: AnRui
 * @note  : 把数据放到数据寄存器中会自动的把数据放到移位寄存器中
 *          数据寄存器为空 就可以继续放下一个数据啦
 *          移位寄存器为空 说明数据发送完毕
 *          一次发送1字节(8bit)数据
 *          usart_flag_get  结果是RESET 代表不为空
 *          如果发送完 需要关闭发送功能  需要等待移位寄存器为空
 */
void UsartSendByte(uint8_t value) {
    // 把数据放到数据寄存器
    usart_data_transmit(UsartInfo.uartNo, value);
    // 等待数据寄存器为空 
    while (RESET == usart_flag_get(UsartInfo.uartNo, USART_FLAG_TBE));
}

/**
 * @desc  : printf函数默认打印输出到显示器，如果要输出到串口，必须重新实现fputc函数，将输出指向串口，称为重定向
 * @date  : 2025-03-25
 * @author: AnRui
 * @param : ch - {参数说明}:
 * @param : f - {参数说明}:
 * @return: int
 * @note  :
 */
int fputc(int ch, FILE* f) {
    UsartSendByte((uint8_t)ch);
    return ch;
}


/**
 * @desc  : 注册usart中断回调函数
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : func - {参数说明}:
 * @note  : 哪个功能需要接收usart数据 就把自己的接受数据的函数注册到regUsartInteruptCallFunc
 *          注意:regUsartInteruptCallFunc这个函数是在usart的中断中被调用 不可以写复杂的逻辑
 */
void regUsartInteruptCallFunc(void (*func)(uint8_t* data, uint32_t len)) {
//    pProcUartIdelIteruptFunc = func;
}

/**
 * @desc  : usart中断接收
 * @date  : 2025-03-26
 * @author: AnRui
 * @note  :
 */
//void USART0_IRQHandler(void) {
//    uint32_t rcvDataLen = 0;
//    if (usart_interrupt_flag_get(UsartInfo.uartNo, USART_INT_FLAG_IDLE) != RESET) {
//        // 清除 空闲状态标志位
//        usart_interrupt_flag_clear(UsartInfo.uartNo, USART_INT_FLAG_IDLE);
//        // 清除 缓冲区(非空)标志位
//        usart_data_receive(UsartInfo.uartNo);
//        dma_channel_disable(UsartInfo.dmaNo, UsartInfo.dmaCh);
//        rcvDataLen = USART_DMA_DATA_BUFF_LEN - dma_transfer_number_get(UsartInfo.dmaNo, UsartInfo.dmaCh);
//        pProcUartIdelIteruptFunc(UsartDmaDataBuff, rcvDataLen);
////        UsartDmaDataBuff[rcvDataLen] = '\0';
////        printf("%s\r\n", UsartDmaDataBuff);
//        dma_transfer_number_config(UsartInfo.dmaNo, UsartInfo.dmaCh, USART_DMA_DATA_BUFF_LEN);
//        dma_channel_enable(UsartInfo.dmaNo, UsartInfo.dmaCh);
//    }
//}


/**
 * @desc  : usart 初始化
 * @date  : 2025-03-25
 * @author: AnRui
 * @note  : 包含引脚 usart外设 dma外设 初始化
 */
void UsartDrvInit(void) {
    UsartGPIOInit();
    UsartPeriphInit();
//    UsartDmaInit();
}


